/**
 * 认证服务类
 * Authentication Service Class
 */

const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');
const config = require('../config/config');
const logger = require('../utils/logger');
const User = require('../database/models/User');

class AuthService {
  constructor() {
    this.loginAttempts = new Map(); // 存储登录尝试记录
    this.maxLoginAttempts = 5;
    this.lockoutDuration = 15 * 60 * 1000; // 15分钟
  }

  /**
   * 用户登录
   */
  async login(email, password, clientIP, userAgent) {
    try {
      // 检查是否被锁定
      if (this.isAccountLocked(email, clientIP)) {
        throw new Error('账户已被临时锁定，请稍后再试 / Account temporarily locked, please try again later');
      }

      // 验证用户凭据
      const user = await User.validatePassword(email, password);
      
      if (!user) {
        // 记录失败尝试
        this.recordFailedAttempt(email, clientIP);
        throw new Error('邮箱或密码错误 / Invalid email or password');
      }

      // 清除失败尝试记录
      this.clearFailedAttempts(email, clientIP);

      // 更新最后登录信息
      await User.updateLastLogin(user.id, clientIP);

      logger.info('用户登录成功 / User login successful', {
        userId: user.id,
        email: user.email,
        ip: clientIP
      });

      return user;
    } catch (error) {
      logger.error('登录失败 / Login failed', {
        email,
        ip: clientIP,
        error: error.message
      });
      throw error;
    }
  }

  /**
   * 检查账户是否被锁定
   */
  isAccountLocked(email, clientIP) {
    const key = `${email}-${clientIP}`;
    const attempts = this.loginAttempts.get(key);
    
    if (!attempts) {
      return false;
    }

    const now = Date.now();
    
    // 清理过期的尝试记录
    attempts.timestamps = attempts.timestamps.filter(
      timestamp => now - timestamp < this.lockoutDuration
    );

    if (attempts.timestamps.length === 0) {
      this.loginAttempts.delete(key);
      return false;
    }

    return attempts.timestamps.length >= this.maxLoginAttempts;
  }

  /**
   * 记录失败尝试
   */
  recordFailedAttempt(email, clientIP) {
    const key = `${email}-${clientIP}`;
    const now = Date.now();
    
    if (!this.loginAttempts.has(key)) {
      this.loginAttempts.set(key, { timestamps: [] });
    }

    const attempts = this.loginAttempts.get(key);
    attempts.timestamps.push(now);

    // 只保留最近的尝试记录
    attempts.timestamps = attempts.timestamps
      .filter(timestamp => now - timestamp < this.lockoutDuration)
      .slice(-this.maxLoginAttempts);
  }

  /**
   * 清除失败尝试记录
   */
  clearFailedAttempts(email, clientIP) {
    const key = `${email}-${clientIP}`;
    this.loginAttempts.delete(key);
  }
  /**
   * 验证密码强度
   */
  validatePasswordStrength(password) {
    const minLength = 6;
    const hasUpperCase = /[A-Z]/.test(password);
    const hasLowerCase = /[a-z]/.test(password);
    const hasNumbers = /\d/.test(password);
    const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password);

    const errors = [];

    if (password.length < minLength) {
      errors.push(`密码至少${minLength}位字符 / Password must be at least ${minLength} characters`);
    }

    // 对于生产环境，可以启用更严格的密码要求
    if (process.env.NODE_ENV === 'production') {
      if (!hasUpperCase) {
        errors.push('密码必须包含大写字母 / Password must contain uppercase letters');
      }
      if (!hasLowerCase) {
        errors.push('密码必须包含小写字母 / Password must contain lowercase letters');
      }
      if (!hasNumbers) {
        errors.push('密码必须包含数字 / Password must contain numbers');
      }
    }

    return {
      isValid: errors.length === 0,
      errors,
      strength: this.calculatePasswordStrength(password)
    };
  }

  /**
   * 计算密码强度
   */
  calculatePasswordStrength(password) {
    let score = 0;
    
    // 长度评分
    if (password.length >= 8) score += 1;
    if (password.length >= 12) score += 1;
    
    // 字符类型评分
    if (/[a-z]/.test(password)) score += 1;
    if (/[A-Z]/.test(password)) score += 1;
    if (/\d/.test(password)) score += 1;
    if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score += 1;
    
    // 复杂度评分
    if (password.length >= 10 && /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])/.test(password)) {
      score += 1;
    }

    if (score <= 2) return 'weak';
    if (score <= 4) return 'medium';
    return 'strong';
  }

  /**
   * 生成安全的随机密码
   */
  generateSecurePassword(length = 12) {
    const lowercase = 'abcdefghijklmnopqrstuvwxyz';
    const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    const numbers = '0123456789';
    const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
    
    const allChars = lowercase + uppercase + numbers + symbols;
    let password = '';
    
    // 确保至少包含每种类型的字符
    password += lowercase[Math.floor(Math.random() * lowercase.length)];
    password += uppercase[Math.floor(Math.random() * uppercase.length)];
    password += numbers[Math.floor(Math.random() * numbers.length)];
    password += symbols[Math.floor(Math.random() * symbols.length)];
    
    // 填充剩余长度
    for (let i = 4; i < length; i++) {
      password += allChars[Math.floor(Math.random() * allChars.length)];
    }
    
    // 打乱字符顺序
    return password.split('').sort(() => Math.random() - 0.5).join('');
  }

  /**
   * 清理过期的登录尝试记录
   */
  cleanupExpiredAttempts() {
    const now = Date.now();
    
    for (const [key, attempts] of this.loginAttempts.entries()) {
      attempts.timestamps = attempts.timestamps.filter(
        timestamp => now - timestamp < this.lockoutDuration
      );
      
      if (attempts.timestamps.length === 0) {
        this.loginAttempts.delete(key);
      }
    }
  }

  /**
   * 获取登录尝试统计
   */
  getLoginAttemptStats() {
    const now = Date.now();
    let totalAttempts = 0;
    let lockedAccounts = 0;
    
    for (const [key, attempts] of this.loginAttempts.entries()) {
      const validAttempts = attempts.timestamps.filter(
        timestamp => now - timestamp < this.lockoutDuration
      );
      
      totalAttempts += validAttempts.length;
      
      if (validAttempts.length >= this.maxLoginAttempts) {
        lockedAccounts++;
      }
    }
    
    return {
      totalAttempts,
      lockedAccounts,
      uniqueIPs: this.loginAttempts.size
    };
  }
}

// 定期清理过期的登录尝试记录（每小时执行一次）
const authService = new AuthService();
setInterval(() => {
  authService.cleanupExpiredAttempts();
}, 60 * 60 * 1000);

module.exports = authService;